﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;

namespace TC.Vacation.Spider.Web
{
    /// <summary>
    /// 异步请求的一个队列实现
    /// </summary>
    public class AsyncRequestQueue : IAsyncRequestQueue, IDisposable
    {
        private Lazy<ConcurrentStack<string>> QueueStack = new Lazy<ConcurrentStack<string>>();
        private Lazy<ConcurrentBag<ICsqWebResponse>> WebResponse = new Lazy<ConcurrentBag<ICsqWebResponse>>();
        private ServerConfig _Options;
        private ICsqWebResponse Response;
        private RequestState RequestState;

        public void AddRequest(string url)
        {
            Queue.Push(url);
        }

        /// <summary>
        /// 响应结果集
        /// </summary>
        /// <returns></returns>
        public IEnumerable<ICsqWebResponse> Results
        {
            get
            {
                return Single.AsEnumerable();
            }
        }

        /// <summary>
        /// Gets the queue.
        /// </summary>
        /// <value>
        /// The queue.
        /// </value>
        public ConcurrentStack<string> Queue
        {
            get
            {
                return QueueStack.Value;
            }
        }

        /// <summary>
        /// Gets the single.
        /// </summary>
        /// <value>
        /// The single.
        /// </value>
        public ConcurrentBag<ICsqWebResponse> Single
        {
            get
            {
                return WebResponse.Value;
            }
        }

        /// <summary>
        /// 请求状态
        /// </summary>
        public RequestState State
        {
            get
            {
                return RequestState;
            }
        }

        /// <summary>
        /// 请求的URL
        /// </summary>
        public string Url
        {
            get;
            protected set;
        }

        /// <summary>
        /// 标识请求是否完成
        /// </summary>
        public bool Complete
        {
            get
            {
                return Response.Complete;
            }
        }

        /// <summary>
        /// 请求完成后返回的唯一标识
        /// </summary>
        public object Id
        {
            get;
            set;
        }

        /// <summary>
        /// 请求配置项
        /// </summary>
        public ServerConfig Options
        {
            get
            {
                return _Options ?? ServerConfig.Default;
            }
            set
            {
                _Options = value;
            }
        }

        /// <summary>
        /// 请求超时--秒
        /// </summary>
        public int Timeout
        {
            get
            {
                return Response.Timeout;
            }
            set
            {
                if (value > 0)
                {
                    Options.Timeout = TimeSpan.FromSeconds(value);
                }
            }
        }

        /// <summary>
        /// 浏览器标识
        /// </summary>
        public string UserAgent
        {
            get
            {
                return Response.UserAgent;
            }
            set
            {
                if (value != null)
                {
                    Options.UserAgent = value;
                }
            }
        }

        /// <summary>
        /// 开始异步队列
        /// </summary>
        public void StartAsyncQueue()
        {
            RequestState = Web.RequestState.Active;
            string url = string.Empty;
            while (Queue.TryPop(out url))
            {
                Url = url;

                Id = AsyncWebRequestManager.StartAsyncWebRequest(url, x =>
                    {
                        Response = x;
                        Single.Add(x);
                        RequestState = Web.RequestState.PartialSuccess;
                    },
                    p =>
                    {
                        Response = p;
                        RequestState = Web.RequestState.Fail;
                    }, Options);
            }
            RequestState = Web.RequestState.Success;
        }

        /// <summary>
        /// 执行与释放或重置非托管资源相关的应用程序定义的任务。
        /// </summary>
        public void Dispose()
        {
            AsyncWebRequestManager.CancelAsyncEvents();
            RequestState = Web.RequestState.Success;
        }
    }
}
